importScripts('../libs/delaunator.js');

let VC; // 顶点容器
let DVC; // 完整顶点容器

this.addEventListener('message', function (e) {
    let data = e.data;
    switch (data.cmd) {
        case 'start':
            this.postMessage('WORKER STARTED: ' + data.msg);
            break;
        case 'stop':
            this.postMessage('WORKER STOPPED: ' + data.msg);
            this.close(); // Terminates the worker.
            break;

        // 土地
        case 'Land':
            landHandle(data.params);
            break;

        // 疏浚工作
        case 'Dredging':
            vertexDecline(data.params.rake);
            break;


        // 全部土地
        case 'DetailLand':
            detailLandHandle(data.params);
            break;

        // 计算裁剪面
        case 'CuttingSurface':
            // lineIntersection(data.params.v1, data.params.v2);
            // lineIntersection222(data.params.v1, data.params.v2);
            lineIntersection333(data.params.v1, data.params.v2);
            break;

        default:
            break;
    };
}, false);

// 判断点在圆内
function insideCircle(p, c, r) {
    let dx = c.x - p.x, dy = c.y - p.y;
    return dx * dx + dy * dy <= r * r;
}

// 判断点在多边形内
function insidePolygon(p, ps) {
    let x = p.x, y = p.y;
    let inside = false;
    for (let i = 0, j = ps.length - 1; i < ps.length; j = i++) {
        let xi = ps[i].x, yi = ps[i].y;
        let xj = ps[j].x, yj = ps[j].y;

        let intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }
    return inside;
};

function zoom(ps, offset) {

    let array = [];

    for (let i = 0, len = ps.length; i < len; i++) {
        let curP = ps[i];

        let lastP = (i == 0) ? ps[len - 1] : ps[i - 1],
            nextP = (i == len - 1) ? ps[0] : ps[i + 1];

        let vec1 = { x: lastP.x - curP.x, y: lastP.y - curP.y },
            vec2 = { x: nextP.x - curP.x, y: nextP.y - curP.y };

        console.log(vec1, vec2);

        let scalar1 = 1 / (Math.sqrt(vec1.x * vec1.x + vec1.y * vec1.y) || 1),
            scalar2 = 1 / (Math.sqrt(vec2.x * vec2.x + vec2.y * vec2.y) || 1);

        vec1.x *= scalar1;
        vec1.y *= scalar1;
        vec2.x *= scalar2;
        vec2.y *= scalar2;

        let normVec = { x: vec1.x + vec2.x, y: vec1.y + vec2.y };

        let scalar = 1 / (Math.sqrt(normVec.x * normVec.x + normVec.y * normVec.y) || 1) * offset;

        normVec.x *= scalar;
        normVec.y *= scalar;

        array.push({ X: curP.x + normVec.x, Y: curP.y + normVec.y, Z: 14.335 });

    }

    return array;

}

// Delaunator化过程
function delaunatorProcess(params) {

    // 提取顶点信息
    let array = [], position = [];
    for (let i = 0, len = params.length; i < len; i++) {
        array.push([params[i].X, params[i].Y]);
    }

    // 格式化且计算三角面索引
    let triangles = Delaunator.from(array).triangles;

    for (let i = 0, len = triangles.length; i < len; i += 3) {
        position.push(
            params[triangles[i]].X, - params[triangles[i]].Z, params[triangles[i]].Y,
            params[triangles[i + 1]].X, - params[triangles[i + 1]].Z, params[triangles[i + 1]].Y,
            params[triangles[i + 2]].X, - params[triangles[i + 2]].Z, params[triangles[i + 2]].Y);
    }

    VC = position;

    return new Float32Array(position);
}

// 地质数据处理
function landHandle(params) {

    let currArea, arr1 = [], arr2 = [], arr3 = [];

    for (let i = 0, len = params.length; i < len; i++) {

        let { XYZs, mode, atSquare } = thisParam = params[i];

        if (atSquare) currArea = [thisParam.minx, thisParam.miny, thisParam.maxx, thisParam.maxy];

        if (XYZs.length > 0) {
            for (let j = 0, jlen = XYZs.length; j < jlen; j++) {

                // XYZs[j].Y = - XYZs[j].Y;
                // const { X, Y } = XYZs[j];
                // arr1.push(XYZs[j]);
                // arr2.push([X, Y]);

                if (mode === 'detail' && j % 3 === 0) {
                    XYZs[j].Y = - XYZs[j].Y;
                    const { X, Y } = XYZs[j];
                    arr1.push(XYZs[j]);
                    arr2.push([X, Y]);
                } else if (mode === 'simple') {
                    XYZs[j].Y = - XYZs[j].Y;
                    const { X, Y } = XYZs[j];
                    arr1.push(XYZs[j]);
                    arr2.push([X, Y]);
                }
            }
        }
    }

    // 格式化且计算三角面索引
    let triangles = Delaunator.from(arr2).triangles;

    for (let i = 0, len = triangles.length; i < len; i += 3) {
        arr3.push(
            arr1[triangles[i]].X, - arr1[triangles[i]].Z, arr1[triangles[i]].Y,
            arr1[triangles[i + 1]].X, - arr1[triangles[i + 1]].Z, arr1[triangles[i + 1]].Y,
            arr1[triangles[i + 2]].X, - arr1[triangles[i + 2]].Z, arr1[triangles[i + 2]].Y);
    }

    VC = arr3;

    this.postMessage({
        cmd: 'Land',
        params: {
            currArea,
            vertices: new Float32Array(arr3),
        }
    });

}

// 全部地质数据处理
function detailLandHandle(params) {

    let arr1 = [], arr2 = [], arr3 = [];

    for (let i = 0, len = params.length; i < len; i++) {

        let XYZs = params[i].XYZs;

        if (XYZs.length > 0) {
            for (let j = 0, jlen = XYZs.length; j < jlen; j++) {
                XYZs[j].Y = - XYZs[j].Y;
                const { X, Y } = XYZs[j];
                arr1.push(XYZs[j]);
                arr2.push([X, Y]);
            }
        }
    }

    // 格式化且计算三角面索引
    let triangles = Delaunator.from(arr2).triangles;

    for (let i = 0, len = triangles.length; i < len; i += 3) {
        arr3.push(
            arr1[triangles[i]].X, - arr1[triangles[i]].Z, arr1[triangles[i]].Y,
            arr1[triangles[i + 1]].X, - arr1[triangles[i + 1]].Z, arr1[triangles[i + 1]].Y,
            arr1[triangles[i + 2]].X, - arr1[triangles[i + 2]].Z, arr1[triangles[i + 2]].Y);
    }

    DVC = arr3;

    this.postMessage({
        cmd: 'DetailLand',
        params: new Float32Array(arr3),
    });

}

/**
 * 顶点下降
 * @param {*} rake 耙得数据
 */
function vertexDecline(rake) {
    const { position: { x, y }, depth } = rake;
    for (let i = 0, len = VC.length; i < len; i += 3) {
        let dx = VC[i] - x, dy = VC[i + 2] - y;
        if (dx * dx + dy * dy <= 4) VC[i + 1] = -depth;
    }
    this.postMessage({
        cmd: 'Dredging',
        params: new Float32Array(VC),
    });
}

// 计算线相交划过的三角面顶点
function lineIntersection(v1, v2) {

    let arr = [];

    for (let i = 0, len = DVC.length; i < len; i += 9) {

        let pp1 = { x: DVC[i], y: DVC[i + 1], z: DVC[i + 2] },
            pp2 = { x: DVC[i + 3], y: DVC[i + 4], z: DVC[i + 5] },
            pp3 = { x: DVC[i + 6], y: DVC[i + 7], z: DVC[i + 8] };

        let p = ValidPoint(v1, v2, pp1, pp2, pp3);

        if (p) {
            arr.push(p);
        }

    }

    arr.push({ x: Number(Distance(v1, v2).toFixed(2)), y: Number(v2.y.toFixed(2)) });

    arr.sort(sort('x')); // 根据距离排序

    // console.log(arr);
    // console.log(JSON.stringify(arr));

    this.postMessage({
        cmd: 'CuttingSurface',
        params: arr
    });

}

// 排序
function sort(property) {
    return function (a, b) {
        return (a[property] - b[property])
    }
}

let insideArray = []; // 交点数组
let nearArray = []; // 临近点
function lineIntersection222(b, c) {

    console.log(Distance(b, c));

    insideArray.splice(0, insideArray.length); // 数组清空
    nearArray.splice(0, nearArray.length);

    let minx = Math.min(b.x, c.x),
        maxx = Math.max(b.x, c.x),
        minz = Math.min(b.z, c.z),
        maxz = Math.max(b.z, c.z);

    let dist;

    let a = { x: (b.x + c.x) / 2, y: (b.y + c.y) / 2, z: (b.z + c.z) / 2 };

    // 求平面的法向量
    let e1 = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z },
        e2 = { x: a.x - c.x, y: a.y - c.y, z: a.z - c.z },
        // 叉乘公式：c = a×b = （a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y）
        n = {
            x: e1.y * e2.z - e1.z * e2.y,
            y: e1.z * e2.x - e1.x * e2.z,
            z: e1.x * e2.y - e1.y * e2.x,
        };

    for (let i = 0, len = DVC.length; i < len; i += 9) {

        let p1 = { x: DVC[i], y: DVC[i + 1], z: DVC[i + 2] },
            p2 = { x: DVC[i + 3], y: DVC[i + 4], z: DVC[i + 5] },
            p3 = { x: DVC[i + 6], y: DVC[i + 7], z: DVC[i + 8] };

        let n1 = { x: p1.x - p2.x, y: p1.y - p2.y, z: p1.z - p2.z },
            n2 = { x: p2.x - p3.x, y: p2.y - p3.y, z: p2.z - p3.z },
            n3 = { x: p3.x - p1.x, y: p3.y - p1.y, z: p3.z - p1.z };

        let pp1 = CalPlaneLineIntersectPoint(n, a, n1, p1),
            pp2 = CalPlaneLineIntersectPoint(n, a, n2, p2),
            pp3 = CalPlaneLineIntersectPoint(n, a, n3, p3);

        if (pp1.x >= minx && pp1.x <= maxx && pp1.z >= minz && pp1.z <= maxz) {
            dist = Number(Distance(b, pp1).toFixed(2));
            if (!nearArray.includes(dist)) {
                nearArray.push(dist);
                insideArray.push({ x: Number(dist), y: Number(pp1.y.toFixed(2)) });
            }
        }
        if (pp2.x >= minx && pp2.x <= maxx && pp2.z >= minz && pp2.z <= maxz) {
            dist = Number(Distance(b, pp2).toFixed(2));
            if (!nearArray.includes(dist)) {
                nearArray.push(dist);
                insideArray.push({ x: Number(dist), y: Number(pp2.y.toFixed(2)) });
            }
        }
        if (pp3.x >= minx && pp3.x <= maxx && pp3.z >= minz && pp3.z <= maxz) {
            dist = Number(Distance(b, pp3).toFixed(2));
            if (!nearArray.includes(dist)) {
                nearArray.push(dist);
                insideArray.push({ x: Number(dist), y: Number(pp3.y.toFixed(2)) });
            }
        }
    }

    insideArray.sort(sort('x')); // 根据距离排序

    console.log(insideArray);
    console.log(JSON.stringify(insideArray));



}

// 计算线段与三角面的交点
function ValidPoint(v1, v2, a, b, c) {
    // 求平面的法向量
    let e1 = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z },
        e2 = { x: a.x - c.x, y: a.y - c.y, z: a.z - c.z },
        // 叉乘公式：c = a×b = （a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y）
        n = {
            x: e1.y * e2.z - e1.z * e2.y,
            y: e1.z * e2.x - e1.x * e2.z,
            z: e1.x * e2.y - e1.y * e2.x,
        };

    //计算常数项
    let TriD = -(n.x * a.x + n.y * a.y + n.z * a.z);
    let LineV = { x: v2.x - v1.x, y: v2.y - v1.y, z: v2.z - v1.z };

    /*-------求解直线与平面的交点坐标---------*/
	/* 思路：
	* 首先将直线方程转换为参数方程形式，然后代入平面方程，求得参数t，
	* 将t代入直线的参数方程即可求出交点坐标
    */

    let tempU = n.x * v1.x + n.y * v1.y
        + n.z * v1.z + TriD;
    let tempD = n.x * LineV.x + n.y * LineV.y + n.z * LineV.z;


    //直线与平面平行或在平面上
    if (tempD == 0.0) {
        return false;
    }

    //计算参数t
    let t = -tempU / tempD;
    //计算交点坐标

    let CrossPoint = {
        x: LineV.x * t + v1.x,
        y: LineV.y * t + v1.y,
        z: LineV.z * t + v1.z,
    };

    /*----------判断交点是否在三角形内部---*/

    //计算三角形三条边的长度
    let d12 = Distance(a, b);
    let d13 = Distance(a, c);
    let d23 = Distance(b, c);
    //计算交点到三个顶点的长度
    let c1 = Distance(CrossPoint, a);
    let c2 = Distance(CrossPoint, b);
    let c3 = Distance(CrossPoint, c);
    //求三角形及子三角形的面积
    let areaD = Area(d12, d13, d23); //三角形面积
    let area1 = Area(c1, c2, d12); //子三角形1
    let area2 = Area(c1, c3, d13); //子三角形2
    let area3 = Area(c2, c3, d23); //子三角形3
    //根据面积判断点是否在三角形内部
    if (Math.abs(area1 + area2 + area3 - areaD) > 0.001) {
        return false;
    }

    console.log(Distance(v1, CrossPoint));


    return {
        x: Number(Distance(v1, CrossPoint).toFixed(2)),
        y: Number(CrossPoint.y.toFixed(2))
    };

}

// 三维点求距离
function Distance(p1, p2) {
    let dist = ((p2.x - p1.x) * (p2.x - p1.x)
        + (p2.y - p1.y) * (p2.y - p1.y)
        + (p2.z - p1.z) * (p2.z - p1.z));
    return Math.sqrt(dist);
}

// 三角形求面积
function Area(a, b, c) {
    let s = (a + b + c) / 2;
    return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}

function test(params) {
    CalPlaneLineIntersectPoint({ x: 0, y: -10000, z: 0 }, { x: 0, y: 0, z: -50 }, { x: 0, y: 200, z: 0 }, { x: 0, y: 100, z: -25 })
}

test();

function nnnnn(a, b, c) {
    // 求平面的法向量
    let e1 = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z },
        e2 = { x: a.x - c.x, y: a.y - c.y, z: a.z - c.z },
        // 叉乘公式：c = a×b = （a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y）
        n = {
            x: e1.y * e2.z - e1.z * e2.y,
            y: e1.z * e2.x - e1.x * e2.z,
            z: e1.x * e2.y - e1.y * e2.x,
        };

    console.log(n);

}


function CalPlaneLineIntersectPoint(planeVector, planePoint, lineVector, linePoint) {

    let vp1, vp2, vp3, n1, n2, n3, v1, v2, v3, m1, m2, m3, vpt;

    vp1 = planeVector.x;
    vp2 = planeVector.y;
    vp3 = planeVector.z;

    n1 = planePoint.x;
    n2 = planePoint.y;
    n3 = planePoint.z;

    v1 = lineVector.x;
    v2 = lineVector.y;
    v3 = lineVector.z;

    m1 = linePoint.x;
    m2 = linePoint.y;
    m3 = linePoint.z;

    vpt = v1 * vp1 + v2 * vp2 + v3 * vp3;

    //首先判断直线是否与平面平行
    if (vpt == 0) {
        return false;
    } else {
        let t = ((n1 - m1) * vp1 + (n2 - m2) * vp2 + (n3 - m3) * vp3) / vpt;

        let zzz = {
            x: m1 + v1 * t,
            y: m2 + v2 * t,
            z: m3 + v3 * t,
        }

        return zzz;
    }
}

function lineIntersection333(v1, v2) {

    v1 = { x: -282.28, y: -14.52, z: 71.16 };
    v2 = { x: -282.28, y: -14.52, z: 101.16 };

    let p1 = { x: -280.28, y: -14.52, z: 71.16 },
        p2 = { x: -284.28, y: -14.52, z: 71.16 },
        p3 = { x: -284.28, y: -14.52, z: 101.16 },
        p4 = { x: -280.28, y: -14.52, z: 101.16 };

    for (let i = 0, len = DVC.length; i < len; i += 3) {

        if (
            insidePolygon({
                x: DVC[i], y: DVC[i + 1], z: DVC[i + 2]
            }, [
                p1, p2, p3, p4
            ])
        ) {

        }
    }



}
